package com.nbcio.pm.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.nbcio.common.core.utils.StringUtils;
import com.nbcio.common.mybatis.core.page.PageQuery;
import com.nbcio.common.mybatis.core.page.TableDataInfo;
import com.nbcio.common.mybatis.helper.DataBaseHelper;
import com.nbcio.common.core.utils.MapstructUtils;
import com.nbcio.pm.domain.PmTimeTracking;
import com.nbcio.pm.domain.bo.PmTimeTrackingBo;
import com.nbcio.pm.domain.vo.PmTimeStatsVo;
import com.nbcio.pm.domain.vo.PmTimeTrackingVo;
import com.nbcio.pm.mapper.PmTimeTrackingMapper;
import com.nbcio.pm.service.IPmTimeTrackingService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Collection;

/**
 * 时间跟踪Service业务层处理
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class PmTimeTrackingServiceImpl implements IPmTimeTrackingService {

    private final PmTimeTrackingMapper baseMapper;

    @Override
    public TableDataInfo<PmTimeTrackingVo> queryPageList(PmTimeTrackingBo bo, PageQuery pageQuery) {
        // 使用自定义查询，包含关联字段
        PmTimeTracking query = new PmTimeTracking();
        query.setTenantId(bo.getTenantId());
        query.setProjectId(bo.getProjectId());
        query.setTaskId(bo.getTaskId());
        query.setUserId(bo.getUserId());
        
        IPage<PmTimeTrackingVo> result = baseMapper.selectPmTimeTrackingList(pageQuery.build(), query);
        return TableDataInfo.build(result);
    }

    private LambdaQueryWrapper<PmTimeTracking> buildQueryWrapper(PmTimeTrackingBo bo) {
        LambdaQueryWrapper<PmTimeTracking> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getProjectId() != null, PmTimeTracking::getProjectId, bo.getProjectId());
        lqw.eq(bo.getTaskId() != null, PmTimeTracking::getTaskId, bo.getTaskId());
        // user_id 现在是单个用户ID
        lqw.eq(bo.getUserId() != null, PmTimeTracking::getUserId, bo.getUserId());
        // 多租户：由 MyBatis Plus TenantLine 统一注入，不再手工拼接
        lqw.orderByDesc(PmTimeTracking::getStartTime);
        return lqw;
    }

    @Transactional(rollbackFor = Exception.class)
    public Boolean insertByBo(PmTimeTrackingBo bo) {
        PmTimeTracking add = MapstructUtils.convert(bo, PmTimeTracking.class);
        return baseMapper.insert(add) > 0;
    }

    @Transactional(rollbackFor = Exception.class)
    public Boolean updateByBo(PmTimeTrackingBo bo) {
        PmTimeTracking update = MapstructUtils.convert(bo, PmTimeTracking.class);
        return baseMapper.updateById(update) > 0;
    }

    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteWithValidByIds(Collection<Long> ids) {
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean startTracking(PmTimeTrackingBo bo) {
        PmTimeTracking record = new PmTimeTracking();
        record.setProjectId(bo.getProjectId());
        record.setTaskId(bo.getTaskId());
        record.setUserId(bo.getUserId());
        record.setStartTime(bo.getStartTime() != null ? bo.getStartTime() : LocalDateTime.now());
        record.setIsBillable(Boolean.TRUE.equals(bo.getIsBillable()));
        record.setHourlyRate(bo.getHourlyRate());
        record.setDescription(bo.getDescription());
        return baseMapper.insert(record) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean stopTracking(Long id) {
        PmTimeTracking exists = baseMapper.selectById(id);
        if (exists == null) {
            return false;
        }
        LocalDateTime end = LocalDateTime.now();
        exists.setEndTime(end);
        if (exists.getStartTime() != null) {
            long minutes = Duration.between(exists.getStartTime(), end).toMinutes();
            BigDecimal hours = new BigDecimal(minutes).divide(new BigDecimal(60), 2, BigDecimal.ROUND_HALF_UP);
            exists.setDuration(hours);
        }
        return baseMapper.updateById(exists) > 0;
    }

    @Override
    public PmTimeStatsVo getUserTimeStats(Long userId, LocalDate startDate, LocalDate endDate) {
        // 使用XML聚合查询或在此处简单占位
        PmTimeTrackingVo vo = baseMapper.selectUserTimeStats(userId, startDate, endDate);
        PmTimeStatsVo stats = new PmTimeStatsVo();
        if (vo != null) {
            stats.setTotalHours(vo.getDuration() == null ? BigDecimal.ZERO : vo.getDuration());
            stats.setBillableHours(vo.getDuration());
            stats.setNonBillableHours(BigDecimal.ZERO);
            stats.setAverageHours(vo.getDuration());
        }
        return stats;
    }

    @Override
    public PmTimeStatsVo getProjectTimeStats(Long projectId, LocalDate startDate, LocalDate endDate) {
        PmTimeTrackingVo vo = baseMapper.selectProjectTimeStats(projectId, startDate, endDate);
        PmTimeStatsVo stats = new PmTimeStatsVo();
        if (vo != null) {
            stats.setTotalHours(vo.getDuration() == null ? BigDecimal.ZERO : vo.getDuration());
            stats.setBillableHours(vo.getDuration());
            stats.setNonBillableHours(BigDecimal.ZERO);
            stats.setAverageHours(vo.getDuration());
        }
        return stats;
    }
}


